package com.anlu.base;

import com.anlu.base.database.DbManager;
import com.anlu.base.database.DbManagerFactory;
import lombok.extern.slf4j.Slf4j;

/**
 * Hello world!
 *
 */
@Slf4j
public class App 
{

    /**
     * Constant parameter name to use mongoDB.
     */
    private static final String USE_MONGO_DB = "--mongo";
    /**
     * Application manager.
     */
    private final AppManager appManager;

    /**
     * Constructor of current App.
     *
     * @param isMongo boolean
     */
    public App(final boolean isMongo) {
        DbManager dbManager = DbManagerFactory.initDb(isMongo);
        appManager = new AppManager(dbManager);
        appManager.initDb();
    }

    public static void main( String[] args )
    {
        boolean isDbMongo = isDbMongo(args);
        if (isDbMongo) {
            log.info("Using the Mongo database engine to run the application.");
        } else {
            log.info("Using the 'in Memory' database to run the application.");
        }
        App app = new App(isDbMongo);
        app.useReadAndWriteThroughStrategy();
        String splitLine = "==============================================";
        log.info(splitLine);
        app.useReadThroughAndWriteAroundStrategy();
        log.info(splitLine);
        app.useReadThroughAndWriteBehindStrategy();
        log.info(splitLine);
        app.useCacheAsideStategy();
        log.info(splitLine);
    }

    /**
     * Read-through and write-around.
     */
    public void useReadThroughAndWriteAroundStrategy() {
        log.info("# CachingPolicy.AROUND");
        appManager.initCachingPolicy(CachingPolicy.AROUND);

        var userAccount2 = new UserAccount("002", "Jane", "She is a girl.");

        appManager.save(userAccount2);
        log.info(appManager.printCacheContent());
        appManager.find("002");
        log.info(appManager.printCacheContent());
        userAccount2 = appManager.find("002");
        userAccount2.setUserName("Jane G.");
        appManager.save(userAccount2);
        log.info(appManager.printCacheContent());
        appManager.find("002");
        log.info(appManager.printCacheContent());
        appManager.find("002");
    }

    /**
     * Read-through and write-behind.
     */
    public void useReadThroughAndWriteBehindStrategy() {
        log.info("# CachingPolicy.BEHIND");
        appManager.initCachingPolicy(CachingPolicy.BEHIND);

        var userAccount3 = new UserAccount("003",
                "Adam",
                "He likes food.");
        var userAccount4 = new UserAccount("004",
                "Rita",
                "She hates cats.");
        var userAccount5 = new UserAccount("005",
                "Isaac",
                "He is allergic to mustard.");

        appManager.save(userAccount3);
        appManager.save(userAccount4);
        appManager.save(userAccount5);
        log.info(appManager.printCacheContent());
        appManager.find("003");
        log.info(appManager.printCacheContent());
        UserAccount userAccount6 = new UserAccount("006",
                "Yasha",
                "She is an only child.");
        appManager.save(userAccount6);
        log.info(appManager.printCacheContent());
        appManager.find("004");
        log.info(appManager.printCacheContent());
    }

    /**
     * Cache-Aside.
     */
    public void useCacheAsideStategy() {
        log.info("# CachingPolicy.ASIDE");
        appManager.initCachingPolicy(CachingPolicy.ASIDE);
        log.info(appManager.printCacheContent());

        var userAccount3 = new UserAccount("003",
                "Adam",
                "He likes food.");
        var userAccount4 = new UserAccount("004",
                "Rita",
                "She hates cats.");
        var userAccount5 = new UserAccount("005",
                "Isaac",
                "He is allergic to mustard.");
        appManager.save(userAccount3);
        appManager.save(userAccount4);
        appManager.save(userAccount5);

        log.info(appManager.printCacheContent());
        appManager.find("003");
        log.info(appManager.printCacheContent());
        appManager.find("004");
        log.info(appManager.printCacheContent());
    }

    /**
     * Check the input parameters. if
     *
     * @param args input params
     * @return true if there is "--mongo" parameter in arguments
     */
    private static boolean isDbMongo(final String[] args) {
        for (String arg : args) {
            if (arg.equals(USE_MONGO_DB)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Read-through and write-through.
     */
    public void useReadAndWriteThroughStrategy() {
        log.info("# CachingPolicy.THROUGH");
        appManager.initCachingPolicy(CachingPolicy.THROUGH);

        var userAccount1 = new UserAccount("001", "John", "He is a boy.");

        appManager.save(userAccount1);
        log.info(appManager.printCacheContent());
        appManager.find("001");
        appManager.find("001");
    }
}
